import {Dictionary} from '@/api/config'
//数据穿梭
export class TransferController<T, K> {
  //左右数据
  private leftData:Array<T>
  private rightData:Array<K>
  private leftKey:string
  private rightKey:string
  //数据穿梭值映射
  private ltrProps:Dictionary<string>
  private rtlProps:Dictionary<string>
  //显示出来的值
  private showLeftData:Array<T>
  private showRightData:Array<K>
  //只转换映射的值
  private onlyLtrProps:boolean
  private onlyRtlProps:boolean
  //搜索数据
  private leftSearchKey:string
  private rightSearchKey:string
  //其他搜索数据
  private leftOrtherKeys:Dictionary<string|undefined>|undefined
  private rightOrtherKeys:Dictionary<string|undefined>|undefined
  //搜索字段
  private leftSearchProps:Array<string>|undefined
  private rightSearchProps:Array<string>|undefined
  constructor(leftData:Array<T>, rightData:Array<K>, ltrProps:Dictionary<string>, rtlProps:Dictionary<string>, leftKey:string, rightKey:string, onlyLtrProps:boolean, onlyRtlProps:boolean, leftSearchProps:Array<string>|undefined, rightSearchProps:Array<string>|undefined) {
    this.leftData = leftData.concat([])
    this.rightData = rightData.concat([])
    this.showLeftData = leftData.concat([])
    this.showRightData = rightData.concat([])
    this.ltrProps = ltrProps
    this.rtlProps = rtlProps
    this.onlyLtrProps = onlyLtrProps
    this.onlyRtlProps = onlyRtlProps
    this.leftSearchKey = ''
    this.rightSearchKey = ''
    this.leftOrtherKeys = undefined
    this.rightOrtherKeys = undefined
    this.leftSearchProps = leftSearchProps
    this.rightSearchProps = rightSearchProps
    this.leftKey = leftKey
    this.rightKey = rightKey
  }

  //更新左边数据
  public changeLeftData(data:Array<T>) {
    this.leftData = data
    this.searchLeftData()
  }

  //更新右边数据
  public changeRightData(data:Array<K>) {
    this.rightData = data
    this.searchRightData()
  }

  //修改左边向右边数据转换
  public changeLtrProps(ltrProps:Dictionary<string>, onlyLtrProps:boolean) {
    this.ltrProps = ltrProps
    this.onlyLtrProps = onlyLtrProps
  }
  //修改右边向左边数据转换
  public changeRtlProps(rtlProps:Dictionary<string>, onlyRtlProps:boolean) {
    this.rtlProps = rtlProps
    this.onlyRtlProps = onlyRtlProps
  }

  /**
   * 修改左边搜索数据
   * @param key 关键字
   * @param ortherKeys 其他搜索项 key对应搜索的key value对应搜索值
   */
  public changeLeftKey(key:string, ortherKeys?:Dictionary<string|undefined>) {
    this.leftSearchKey = key
    if (ortherKeys) this.leftOrtherKeys = ortherKeys
    this.searchLeftData()
  }

  /**
   * 修改右边搜索数据
   * @param key 关键字
   * @param ortherKeys 其他搜索项
   */
  public changeRightKey(key:string, ortherKeys?:Dictionary<string|undefined>) {
    this.rightSearchKey = key
    if (ortherKeys) this.rightOrtherKeys = ortherKeys
    this.searchRightData()
  }

  //获取左边的数据
  public getLeftData() {
    return this.leftData
  }

  //获取右边的数据
  public getRightData() {
    return this.rightData
  }

  //获取左边显示数据
  public getShowLeftData() {
    return this.showLeftData
  }

  //获取右边显示数据
  public getShowRightData() {
    return this.showRightData
  }

  //左向右穿梭
  public ltr(data:Array<T>) {
    const arr = this.swapData<T, K>(this.leftKey, this.leftData, this.rightData, data, this.ltrProps, this.onlyLtrProps)
    this.leftData = arr[0] as Array<T>
    this.rightData = arr[1] as Array<K>
    this.searchLeftData()
    this.searchRightData()
  }
  //右向左穿梭
  public rtl(data:Array<K>, reverse = true) {
    const arr = this.swapData<K, T>(this.rightKey, this.rightData, this.leftData, data, this.rtlProps, this.onlyRtlProps, reverse)
    this.rightData = arr[0] as Array<K>
    this.leftData = arr[1] as Array<T>
    this.searchLeftData()
    this.searchRightData()
  }

  //搜索左边数据
  public searchLeftData() {
    this.showLeftData = this.getSearchData<T>(this.leftData, this.leftSearchKey, this.leftSearchProps, this.leftOrtherKeys)
  }
  //搜索右边数据
  public searchRightData() {
    this.showRightData = this.getSearchData<K>(this.rightData, this.rightSearchKey, this.rightSearchProps, this.rightOrtherKeys)
  }

  //穿梭数据
  private swapData<F, T>(fromKey:string, fromArr:Array<F>, toArr:Array<T>, transfData:Array<F>, transfProps:Dictionary<string>, onlyTransProps:boolean, reverse?:boolean):Array<Array<F>|Array<T>> {
    if (transfData.length === 0 || !fromKey) {
      return [fromArr, toArr]
    } else {

      //首先剔除源数据
      const newFromArr:Array<F> = []
      const orginToArr:Array <T> = toArr.concat([])
      let newToArr:Array <T> = []
      fromArr.forEach((fromItem) => {
        let flag = false
        for (let i = 0, l = transfData.length; i < l; i++) {
          const transItem = transfData[i]
          if (transItem[fromKey] !== undefined && transItem[fromKey] === fromItem[fromKey]) {
            flag = true
            break
          }
        }
        //转换数据
        if (flag) {
          const newTransItem = {} as any
          if (!onlyTransProps) {
            for (const key in fromItem) {
              newTransItem[key] = fromItem[key]
            }
          }
          for (const key in transfProps) {
            if (newTransItem[key]) delete newTransItem[key]
            newTransItem[transfProps[key]] = fromItem[key]
          }
          newToArr.push(newTransItem)
        } else {
          newFromArr.push(fromItem)
        }
      })
      if (reverse) {
        newToArr = newToArr.reverse()
        newToArr = newToArr.concat(orginToArr)
      } else {
        newToArr = orginToArr.concat(newToArr)
      }
      return [newFromArr, newToArr]
    }
  }
  //搜索数据
  private getSearchData<D>(data:Array<D>, searchKey:string, searchProps:Array<string>|undefined, ortherKeys?:Dictionary<string|undefined>):Array<D> {
    if ((!searchKey || !searchProps) && !ortherKeys) {
      return data
    } else {
      const arr:Array<D> = []
      data.forEach((item) => {
        let flag = false
        //一对多
        if (searchKey && searchProps) {
          for (const key of searchProps) {
            const data = item[key]
            if (typeof data === 'number' || typeof data === 'string') {
              //忽略大小写
              const str = (data + '').toLowerCase()
              if (str.indexOf(searchKey.toLowerCase()) !== -1) {
                flag = true
                break
              }
            }
          }
        } else {
          flag = true
        }
        //多对多 通过关键字搜索且还有其他搜索项
        if (ortherKeys && flag) {
          for (const key in ortherKeys) {
            const data = item[key]
            const search = ortherKeys[key]
            if (search && (typeof data === 'number' || typeof data === 'string')) {
              //忽略大小写
              const str = (data + '').toLowerCase()
              if (str.indexOf(search.toLowerCase()) === -1) {
                flag = false
                break
              }
            }
          }
        }
        //成功匹配到
        if (flag) arr.push(item)
      })
      return arr
    }
  }
}